var mongo = require("./mongo_base");
var hp = require("./hp_service");
var http = require("./http_service");
var util = require('./utils/util');
var fs = require('fs');

var self = null;
var cnynld_module_global = {};
module.exports = {
	system_config: null,
	service: {},
	controller: {},
	start() {
		let st = new Date().getTime();
		try {
			self = this;
			self.system_config = require("./../config/system.config");
			if (!self.system_config.http.enable && !self.system_config.hp.enable){
				console.error("http and hp service not open..!");
				process.abort();
				return;
			}
			if(!self.system_config.system.name) throw "service name not set.!";
			mongo.init(self.system_config.mongo);
			hp.start(self.system_config.hp, self.interface_callback);
			http.start(self.system_config.http, self.interface_callback);
			util.vm.init(self.system_config.vm);
			self.init();
			console.log(`system version:${self.system_config.system.version} Initialization complete...time:${ new Date().getTime() - st }ms`);
		}catch (e){
			console.log(`system version:${self.system_config.system.version} Initialization fail...\nmessage:${e} \n stack:${e.stack}`);
			process.abort();
		}
	},
	init() {
		let s_file = {controller:[], entity:[], service:[]};
		(function dir(dirpath) {    //  遍历目录、获取符合规则的后台文件
			
			fs.readdirSync(dirpath).forEach((file) => {
				try {
					let path = dirpath + file;
					if (fs.statSync(path).isDirectory()) dir(path + '/');
					else {
						var match = file.match(/.*?\.(controller|entity|service)\.js/);
						if (!match) return;
						s_file[match[1]].push({service_name: dirpath.replace(self.system_config.system.src_path, "").replace(/(^\/)|(\/$)/g, '').replace(/\//g, "."), path: path});
					}
				}catch (e){}
			})
			
		})(self.system_config.system.src_path);
		
		s_file.entity.forEach((e) => mongo.register_entity(util.vm.load_module(e.path, {}), e.service_name));  //  加载实体，，
		
		s_file.service.forEach((e) => {   //  加载服务，，
			self.service[e.service_name] = util.vm.load_module(e.path, { service_name: e.service_name});
		});
		
		//  注入服务    不放到上面是因为，，上面还没生成完所有服务
		for (let key in self.service){
			let service = self.service[key];
			let mdb = mongo.get_server(key);    //  如果有同名实体对象，注入服务使用的数据库服务
			
			service[self.system_config.system.global_variable_name] = {
				version: self.system_config.system.version,
				serviceNmae: self.system_config.system.name,
				server: mdb && util.object.readOnly(mdb, util.object.clone_func(mdb)),   //  读限制的server
				util: util, //  注入util包
				getEntity: (args) => mongo.get_entity(key),  //  注入getEntity方法  获取当前层实体
				hprose: {      //  注入hprose服务，提供push方法
					push: hp.push
				},
				global:cnynld_module_global //  全局对象,无限对象
			};
			self.inject_service(service);   //  注入引入对象
		}
		
		//  加载接口、控制层
		s_file.controller.forEach((e) => {
			let context = util.vm.load_module(e.path, {});
			context[self.system_config.system.global_variable_name] = {};
			
			let route = { route: e.service_name, public:{}};    //  路由与公开函数
			if (context.config){
				if (self.system_config.system.custom_route && context.config.route)    //  当开启了设置路由功能，则加载配置中route
					route.route = context.config.route;
				route.public = context.config.public;
			}
			if (!route.public) route.public = {};
			
			if (util.object.is_empty(route.public)){ //  当模块未设置可用方法时，，遍历所有函数并公开
				for (let key in context){
					if (typeof context[key] === 'function')
						route.public[key] = { handle:context[key], cache: false};    //  默认不缓存结果
				}
			}else {
				for (let key in route.public){      //  设置过公开的函数，但未设置配置属性，这里添加一些其他的属性，比如是否缓存....
					if (typeof route.public[key] === "function")
						route.public[key] = { handle:route.public[key], cache: false};    //  默认不缓存结果
				}
			}
			self.inject_service(context);
			if (self.controller[route.route]) throw `controller ${route.route} repeat..!`;
			self.controller[route.route] = { self: context, public: route.public };
		});
	},
	inject_service (context) {
		if (!context.config || !context.config.inclucde) return;
		let inclucde = context.config.inclucde;
		for (let key in inclucde){
			let service = null;
			if (self.service[inclucde[key]]) service = self.service[inclucde[key]]; //  使用别名方式引入服务
			else if (self.service[key]) service = self.service[key];    //  直接引入
			
			if (service) {
				var only = util.object.readOnly(service);
				context[self.system_config.system.global_variable_name][key] = only;    //  注入服务
				inclucde[key] = only;
			}
			else console.error(`frame not found service ${key}`);
		}
	},
	interface_callback(route, action, params, callback){
		if (!route) throw `reute is empty..${route}`;
		let controller = self.controller[route];
		if (!controller) throw `no routing information found...${route}`;
		var func = controller.public[action];
		if (!func) throw `no function found...${route}.${action}`;
		
		if (params && params.cnynld_token){
			
			
		}else {
			//throw `user token is empty...${route}.${action},parmas: ${JSON.stringify(params)}`;
		}
		//  验证token、调用日志
		func.handle.call(controller.self, params, function (args1, args2) {
			callback(args1, args2);
		});
	}
};